package com.example.udpdemo.service;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * UDP服务器服务类
 * 使用DatagramPacket实现UDP通信
 *
 * @author demo
 */
@Service
public class UDPServerService {

    private static final Logger log = LoggerFactory.getLogger(UDPServerService.class);

    // UDP服务器端口
    private static final int UDP_PORT = 8888;

    // 缓冲区大小
    private static final int BUFFER_SIZE = 1024;

    // UDP Socket
    private DatagramSocket datagramSocket;

    // 服务器运行状态
    private final AtomicBoolean isRunning = new AtomicBoolean(false);

    // 接收消息计数器
    private final AtomicInteger receivedCount = new AtomicInteger(0);

    // 发送消息计数器
    private final AtomicInteger sentCount = new AtomicInteger(0);

    // 接收线程
    private Thread receiveThread;

    /**
     * 启动UDP服务器
     */
    @PostConstruct
    public void startServer() {
        try {
            // 创建UDP Socket
            datagramSocket = new DatagramSocket(UDP_PORT);
            log.info("UDP服务器启动成功，监听端口: {}", UDP_PORT);

            // 设置服务器运行状态
            isRunning.set(true);

            // 启动接收线程
            startReceiveThread();

        } catch (SocketException e) {
            log.error("UDP服务器启动失败", e);
        }
    }

    /**
     * 启动接收线程
     */
    private void startReceiveThread() {
        receiveThread = new Thread(() -> {
            log.info("UDP接收线程启动");

            while (isRunning.get() && !Thread.currentThread().isInterrupted()) {
                try {
                    // 创建接收缓冲区
                    byte[] buffer = new byte[BUFFER_SIZE];
                    DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);

                    // 接收数据包
                    datagramSocket.receive(receivePacket);

                    // 处理接收到的数据
                    processReceivedPacket(receivePacket);

                } catch (IOException e) {
                    if (isRunning.get()) {
                        log.error("UDP接收数据时发生异常", e);
                    }
                }
            }

            log.info("UDP接收线程结束");
        });

        receiveThread.setName("UDP-Receive-Thread");
        receiveThread.start();
    }

    /**
     * 处理接收到的数据包
     */
    private void processReceivedPacket(DatagramPacket packet) {
        try {
            // 获取发送方信息
            InetAddress senderAddress = packet.getAddress();
            int senderPort = packet.getPort();

            // 获取数据内容
            String message = new String(packet.getData(), 0, packet.getLength(), StandardCharsets.UTF_8);

            // 增加接收计数器
            int count = receivedCount.incrementAndGet();

            log.info("收到来自 {}:{} 的消息 [{}]: {}",
                    senderAddress.getHostAddress(), senderPort, count, message);

            // 发送响应消息
            sendResponse(senderAddress, senderPort, "收到消息: " + message);

        } catch (Exception e) {
            log.error("处理接收数据包时发生异常", e);
        }
    }

    /**
     * 发送响应消息
     */
    private void sendResponse(InetAddress address, int port, String message) {
        try {
            // 将消息转换为字节数组
            byte[] data = message.getBytes(StandardCharsets.UTF_8);

            // 创建发送数据包
            DatagramPacket sendPacket = new DatagramPacket(data, data.length, address, port);

            // 发送数据包
            datagramSocket.send(sendPacket);

            // 增加发送计数器
            int count = sentCount.incrementAndGet();

            log.info("发送响应到 {}:{} [{}]: {}",
                    address.getHostAddress(), port, count, message);

        } catch (IOException e) {
            log.error("发送响应消息时发生异常", e);
        }
    }

    /**
     * 发送UDP消息到指定地址和端口
     */
    public boolean sendMessage(String targetHost, int targetPort, String message) {
        try {
            // 解析目标地址
            InetAddress targetAddress = InetAddress.getByName(targetHost);

            // 将消息转换为字节数组
            byte[] data = message.getBytes(StandardCharsets.UTF_8);

            // 创建发送数据包
            DatagramPacket sendPacket = new DatagramPacket(data, data.length, targetAddress, targetPort);

            // 发送数据包
            datagramSocket.send(sendPacket);

            // 增加发送计数器
            int count = sentCount.incrementAndGet();

            log.info("发送消息到 {}:{} [{}]: {}", targetHost, targetPort, count, message);

            return true;

        } catch (Exception e) {
            log.error("发送UDP消息时发生异常", e);
            return false;
        }
    }

    /**
     * 获取服务器状态信息
     */
    public String getServerStatus() {
        return String.format("UDP服务器状态: %s, 接收消息: %d, 发送消息: %d",
                isRunning.get() ? "运行中" : "已停止",
                receivedCount.get(),
                sentCount.get());
    }

    /**
     * 停止UDP服务器
     */
    @PreDestroy
    public void stopServer() {
        log.info("正在停止UDP服务器...");

        // 设置停止标志
        isRunning.set(false);

        // 中断接收线程
        if (receiveThread != null && receiveThread.isAlive()) {
            receiveThread.interrupt();
        }

        // 关闭Socket
        if (datagramSocket != null && !datagramSocket.isClosed()) {
            datagramSocket.close();
            log.info("UDP服务器已停止");
        }
    }

    /**
     * 检查服务器是否运行
     */
    public boolean isRunning() {
        return isRunning.get();
    }

    /**
     * 获取接收消息数量
     */
    public int getReceivedCount() {
        return receivedCount.get();
    }

    /**
     * 获取发送消息数量
     */
    public int getSentCount() {
        return sentCount.get();
    }
}
